﻿using System;

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace LinqToObjects
{
    public class Bar
    {
        public int Id { get; set; }
        public string Nome { get; set; }
        public string Localidade { get; set; }
        public decimal Entrada { get; set; }
    }

    public class Bebida
    {
        public int Id { get; set; }
        public int IdBar { get; set; }
        public string Nome { get; set; }
        public decimal Preco { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            List<Bar> listaBares = new List<Bar>{
                new Bar{ Id = 1, Nome= "Kapital", Localidade="Lisboa", Entrada = 20 },
                new Bar{ Id = 2, Nome= "Touareg", Localidade="Odivelas", Entrada = 6  },
                new Bar{ Id = 3, Nome= "Quadrados", Localidade="Bobadela", Entrada = 0  },
                new Bar{ Id = 4, Nome= "Cena de Copos", Localidade="Lisboa", Entrada = 0  },
                new Bar{ Id = 5, Nome= "Galerias", Localidade="Bobadela", Entrada = 0  },
                new Bar{ Id = 6, Nome= "Imaginário", Localidade="Odivelas", Entrada = 15  },
            };


            WriteExampleHeading("Exemplo - Bares em Lisboa");

            var baresEmLisboa =
            from bar in listaBares
            where bar.Localidade == "Lisboa"
            orderby bar.Nome
            select bar.Nome;

            WriteResult<string>(baresEmLisboa);




            //WriteExampleHeading("Exemplo - Bares em Lisboa - Traduzido");

            //var baresEmLisboa =
            //    Enumerable.Select(
            //        Enumerable.OrderBy(
            //            Enumerable.Where(listaBares,
            //                        delegate(Bar bar) { return bar.Localidade == "Lisboa"; }),
            //            delegate(Bar bar) { return bar.Nome; }),
            //        delegate(Bar bar) { return bar.Nome; });

            //WriteResult<string>(baresEmLisboa);





            //WriteExampleHeading("Exemplo - Bar com Entrada Mais Cara");

            //Func<Bar, decimal> devolveEntrada = bar => bar.Entrada;

            //var barMaisCaro =
            //        (from bar in listaBares
            //         where bar.Entrada == listaBares.Max(devolveEntrada)
            //         //where bar.Entrada == listaBares.Min(bar2 => bar2.Entrada)
            //         select bar).Single();
            //WriteObject(barMaisCaro);


            // Bebidas

            List<Bebida> listaBebidas = new List<Bebida>{
                new Bebida{ Id = 1, IdBar = 1, Nome= "Kalashnikov", Preco = 4},
                new Bebida{ Id = 2, IdBar = 1, Nome= "Morangoska", Preco = 4},
                new Bebida{ Id = 3, IdBar = 1, Nome= "Whiskey", Preco = 6},
                new Bebida{ Id = 4, IdBar = 2, Nome= "Chá de Menta", Preco = 2.5m},
                new Bebida{ Id = 5, IdBar = 2, Nome= "Chá Exótico", Preco = 2.5m},
                new Bebida{ Id = 6, IdBar = 2, Nome= "Chá dos Amantes", Preco = 2.5m},
                new Bebida{ Id = 7, IdBar = 3, Nome= "Kalashnikov", Preco = 2},
                new Bebida{ Id = 8, IdBar = 3, Nome= "Whiskey", Preco = 4},
                new Bebida{ Id = 9, IdBar = 4, Nome= "Kalashnikov", Preco = 2.5m},
                new Bebida{ Id = 10, IdBar = 4, Nome= "Morangoska", Preco = 2.5m},
                new Bebida{ Id = 11, IdBar = 4, Nome= "Whiskey", Preco = 5},
            };


            //WriteExampleHeading("Exemplo - Bebidas de bares");
            //var resultadosJoin =
            //        from bar in listaBares
            //        join bebida in listaBebidas on bar.Id equals bebida.IdBar
            //        select new
            //        {
            //            NomeBar = bar.Nome,
            //            Bebida = bebida.Nome,
            //        };

            //foreach (var resultadoJoin in resultadosJoin)
            //{
            //    Console.WriteLine("NomeBar = " + resultadoJoin.NomeBar
            //                        + ", Bebida = " + resultadoJoin.Bebida);
            //}





            //WriteExampleHeading("Exemplo - Bares que Sirvam Chá");
            //var baresCha =
            //        from bar in listaBares
            //        join bebida in listaBebidas on bar.Id equals bebida.IdBar
            //        where bebida.Nome.Contains("Chá")
            //        select new
            //        {
            //            NomeBar = bar.Nome,
            //            Bebida = bebida.Nome,
            //        };

            //foreach (var resultadoCha in baresCha)
            //{
            //    Console.WriteLine("NomeBar = " + resultadoCha.NomeBar
            //                        + ", Bebida = " + resultadoCha.Bebida);
            //}

            Console.ReadLine();
        }


        #region Helper Methods

        private static void WriteExampleHeading(string descricaoExemplo)
        {
            if (first)
                first = false;
            else
                Console.WriteLine(Environment.NewLine);
            Console.WriteLine(descricaoExemplo + Environment.NewLine);
        }
        private static void WriteResult<T>(IEnumerable<T> resultados)
        {
            foreach (T resultado in resultados)
            {
                WriteObject(resultado);
            }
        }
        private static void WriteObject(object objectToWrite)
        {
            Bar obj = objectToWrite as Bar;
            if (obj != null)
            {
                Console.WriteLine("Id = " + obj.Id + ", Nome = " + obj.Nome + ", Localidade = " + obj.Localidade + ", Entrada = " + obj.Entrada);
                return;
            }

            Bebida obj2 = objectToWrite as Bebida;
            if (obj2 != null)
            {
                Console.WriteLine("Id = " + obj2.Id + ", BarId = " + obj2.IdBar + ", Nome = " + obj2.Nome + ", Preço = " + obj2.Preco);
                return;
            }

            Console.WriteLine(objectToWrite.ToString());
        }

        static bool first = true;

        #endregion
    }
}
